/*
 * Copyright (c) 2009, Jan Pastor. All Rights Reserved.
 */

package sk.jp.jitag.ui.thumb;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import sk.jp.commons.ui.InfoDialog;
import sk.jp.jitag.vo.file.ImageFile;
import sk.jp.jitag.vo.file.MediaFile;
import sk.jp.jitag.vo.file.MediaTypeVisitor;
import sk.jp.jitag.ui.common.IconLoader;
import sk.jp.jitag.ui.common.Icons;

/**
 * Base file thumbnail component that contains rating in control pane
 * and provides popup menu for actions.
 */
public class FileThumbnail extends AbstractFileThumbnail {

    /**
     * Predefined unique (square) icon size. 
     */
    protected static final int ICNON_SIZE = 16;

    /**
     * Enumeration of rating values supported by this thumbnail presentation component.
     */
    public enum Rating {
        plus2(2, Icons.ratingPlus2),
        plus1(1, Icons.ratingPlus1),
        neutral(0, Icons.ratingNeutral),
        minus1(-1, Icons.ratingMinus1),
        minus2(-2, Icons.ratingMinus2),
        ;
        private int value;
        private Icons icon;
        Rating(int value, Icons icon) {
            this.value = value;
            this.icon = icon;
        }
        public int getValue() {
            return value;
        }
        public Icons getIcon() {
            return icon;
        }
        /**
         * Returns enum item specified by given value.
         * @param value
         * @return enum ite or null if none was found.
         */
        public static Rating valueOf(int value){
            for (Rating rating : values()) {
                if(rating.getValue() == value){
                    return rating;
                }
            }
            return null;
        }
        @Override
        public String toString() {
            return "Rating{" +
                   "value=" + value +
                   '}';
        }
    }

    private final MediaFile mediaFile;
    private JPopupMenu popupMenu = null;
    private JLabel ratingLabel = null;
    private JLabel warnLabel = null;

    //----------------------------------------------------------------------

    /**
     * Setup thumbnail component.
     * @param mediaFile file to present.
     * @param thumbnailSize maximal thumbnail size.
     */
    public FileThumbnail(MediaFile mediaFile, int thumbnailSize) {
        super(thumbnailSize, ICNON_SIZE);

        if(mediaFile == null) throw new NullPointerException("Parameter mediaFile is null");
        this.mediaFile = mediaFile;

        init();
        onTagsChanged();
        onRatingChanged();
    }

    //----------------------------------------------------------------------

    /**
     * Returns media file assigned to this thumbnail component.
     * @return media file assigned to this thumbnail component.
     */
    public MediaFile getMediaFile() {
        return mediaFile;
    }

    /**
     * Process change of tags of assigned media file.
     */
    public void onTagsChanged(){
        if(warnLabel == null){
            return;
        }
        if(mediaFile.getTags().isEmpty()){
            warnLabel.setIcon(IconLoader.loadIcon(Icons.warn));
        }else{
            warnLabel.setText("");
        }
    }

    /**
     * Process change of rating of assigned media file.
     */
    public void onRatingChanged(){
        if(ratingLabel == null){
            return;
        }
        int fileRating = mediaFile.getRating().getValue();
        Rating rating = Rating.valueOf(fileRating);
        if(rating != null){
            ratingLabel.setIcon(IconLoader.loadIcon(rating.getIcon()));
        }else{
            ratingLabel.setIcon(IconLoader.loadIcon(Rating.neutral.getIcon()));
        }
    }

    //----------------------------------------------------------------------

    /**
     * Setup controls panel and others.
     */
    protected void init(){
        setLayout(null);

        Rectangle controlsBounds = countControlsBounds();

        ratingLabel = new JLabel();
        add(ratingLabel);
        ratingLabel.setBounds(controlsBounds.x, controlsBounds.y,
                         ICNON_SIZE * 5, ICNON_SIZE);

        warnLabel = new JLabel();
        add(warnLabel);
        warnLabel.setBounds(controlsBounds.x + ICNON_SIZE * 5 + 8, controlsBounds.y,
                            ICNON_SIZE, ICNON_SIZE);

        popupMenu = createPopupMenu();

        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent event) {
                if(event.getButton() == MouseEvent.BUTTON3 || event.isPopupTrigger()){
                    processMouseRightClick(event);
                }else if(event.getButton() == MouseEvent.BUTTON1 && event.getClickCount() > 1){
                    processMouseDoubleClick();
                }
            }
        });
    }

    @Override
    protected void paintThumbnailContent(Graphics2D g2d) {
        final Image[] thumbnail = new Image[1];
        mediaFile.accept(new MediaTypeVisitor() {
            public void visit(ImageFile file) {
                thumbnail[0] = IconLoader.loadIcon(Icons.image).getImage();
            }
        });
        Point thumbnailLocation = countThumbnailRealLocation(
                        new Dimension(thumbnail[0].getWidth(null),
                                      thumbnail[0].getHeight(null)));

        g2d.drawImage(thumbnail[0], thumbnailLocation.x, thumbnailLocation.y, null);
    }

    /**
     * Builds popup menu for this thumbnail component.
     * @return popup menu instance or null if this thumbnail component has not
     * popup menu.
     */
    protected JPopupMenu createPopupMenu(){
        JPopupMenu menu = new JPopupMenu();

        //TODO Dokoncit!!!

        //TODO test
        JMenuItem mi = new JMenuItem("Rotat left");
        menu.add(mi);
        mi.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("##### FILE rotate left: "+FileThumbnail.this.getMediaFile().getInfo().getFilePath());//TODO test
            }
        });
        menu.add(new JMenuItem("Rotat right"));
        menu.add(new JMenuItem("Show file info"));


        final JMenu pm = new JMenu("Set rating");
        menu.add(pm);
        pm.add(new JMenuItem("   **"));    //TODO Dokoncit!!! radio item
        pm.add(new JMenuItem("   * "));
        pm.add(new JMenuItem("     "));
        pm.add(new JMenuItem(" *   "));
        pm.add(new JMenuItem("**   "));

        //TODO Dokoncit!!! + menu item: Sync file with database data
        //TODO Dokoncit!!! + menu item: Open with tool...
        //TODO Dokoncit!!! + menu item: File info {date created. date modified, file name, path, }
        // \

        return menu;
    }

    /**
     * Process mouse right click to this thumbnail.
     * <p>By default, shows popup menu (if created).
     * @param event
     */
    protected void processMouseRightClick(MouseEvent event) {
        if(popupMenu == null){
            return;
        }
        if(event instanceof ThumbnailListMouseEvent){
            ThumbnailListMouseEvent tlEvent = (ThumbnailListMouseEvent) event;
            popupMenu.setInvoker(this);
            popupMenu.setLocation(tlEvent.getAbsoluteLocation().x,
                                  tlEvent.getAbsoluteLocation().y);
            popupMenu.setVisible(true);
        }else{
            popupMenu.show(this, event.getX(), event.getY());
        }
    }

    /**
     * Process mouse double click to this thumbnail.
     * <p>By default, delegate this call to central application logic for process.
     */
    protected void processMouseDoubleClick(){
        //TODO Dokoncit!!! open with tool FileThumbnailsPanel.processMouseDoubleClickOnThumbnail(FileTh.)    - tam
        

        new InfoDialog().show(this, "Not implemented yet");
    }

}